package top.cardone.data.jdbc.dao.impl;

import com.google.common.collect.Maps;
import lombok.extern.log4j.Log4j2;
import org.springframework.util.CollectionUtils;
import top.cardone.context.ApplicationContextHolder;
import top.cardone.data.dao.SimpleDao;
import top.cardone.data.jdbc.support.NamedParameterJdbcOperationsSupport;

import java.util.List;
import java.util.Map;

/**
 * Created by yao hai tao on 2015/8/26.
 */
@Log4j2
public class SimpleDaoImpl extends CrudDaoImpl implements SimpleDao {
	@Override
	public <P> List<P> findList(Class<P> mappedClass, Object findList) {
		String sqlFilePath = this.getSqlFilePath("find");

		Map<String, Object> findListMap = this.toMap(findList, "find");

		Map<String, Object> newFindListMap = Maps.newHashMap();

		for (Map.Entry<String, Object> findListEntry : findListMap.entrySet()) {
			newFindListMap.put("where_and_eq_" + findListEntry.getKey(), Boolean.TRUE.toString());
			newFindListMap.put("where_and_eq_" + findListEntry.getKey() + "_value", findListEntry.getValue());
		}

		return this.findList(mappedClass, sqlFilePath, newFindListMap);
	}

	public <P> List<P> findList(Class<P> mappedClass, String sqlFilePath, Map<String, ?> findList) {
		String parseBeanId = this.getParseBeanId();
		String namedParameterJdbcOperationsBeanId = this.getNamedParameterJdbcOperationsBeanId();

		return (List<P>) ApplicationContextHolder.getBean(NamedParameterJdbcOperationsSupport.class).func(parseBeanId, sqlFilePath, findList, namedParameterJdbcOperationsBeanId, (sql, namedParameterJdbcOperations) -> namedParameterJdbcOperations.query(sql, findList, new org.springframework.jdbc.core.BeanPropertyRowMapper(mappedClass)));
	}

	@Override
	public <P> P findOne(Class<P> mappedClass, Object findOne) {
		String sqlFilePath = this.getSqlFilePath("find");

		Map<String, Object> findOneMap = this.toMap(findOne, "find");

		Map<String, Object> newFindOneMap = Maps.newHashMap();

		for (Map.Entry<String, Object> findOneEntry : findOneMap.entrySet()) {
			newFindOneMap.put("where_and_eq_" + findOneEntry.getKey(), Boolean.TRUE.toString());
			newFindOneMap.put("where_and_eq_" + findOneEntry.getKey() + "_value", findOneEntry.getValue());
		}

		return this.findOne(mappedClass, sqlFilePath, newFindOneMap);
	}

	protected <P> P findOne(Class<P> mappedClass, String sqlFilePath, Map<String, ?> findOne) {
		List<P> findList = this.findList(mappedClass, sqlFilePath, findOne);

		if (CollectionUtils.isEmpty(findList)) {
			return null;
		}

		if (findList.size() > 1) {
			log.error("单条数据查询方法，查询出" + findList.size() + "条数据:sqlFilePath=" + sqlFilePath + ", findOne=" + findOne);
		}

		return findList.get(0);
	}

	@Override
	public <R> List<R> readList(Class<R> requiredType, Object readList) {
		String sqlFilePath = this.getSqlFilePath("read");

		Map<String, Object> readListMap = this.toMap(readList, "read");

		Map<String, Object> newReadListMap = Maps.newHashMap();

		for (Map.Entry<String, Object> readListEntry : readListMap.entrySet()) {
			if ("object_id".equals(readListEntry.getKey())) {
				continue;
			}

			newReadListMap.put("where_and_eq_" + readListEntry.getKey(), Boolean.TRUE.toString());
			newReadListMap.put("where_and_eq_" + readListEntry.getKey() + "_value", readListEntry.getValue());
		}

		newReadListMap.put("object_id", readListMap.get("object_id"));

		return this.readList(requiredType, sqlFilePath, newReadListMap);
	}

	protected <R> List<R> readList(Class<R> requiredType, String sqlFilePath, Map<String, ?> readList) {
		String parseBeanId = this.getParseBeanId();
		String namedParameterJdbcOperationsBeanId = this.getNamedParameterJdbcOperationsBeanId();

		return ApplicationContextHolder.getBean(NamedParameterJdbcOperationsSupport.class).func(parseBeanId, sqlFilePath, readList, namedParameterJdbcOperationsBeanId, (sql, namedParameterJdbcOperations) -> namedParameterJdbcOperations.queryForList(sql, readList, requiredType));
	}

	@Override
	public <R> R readOne(Class<R> requiredType, Object readOne) {
		String sqlFilePath = this.getSqlFilePath("read");

		Map<String, Object> readOneMap = this.toMap(readOne, "read");

		Map<String, Object> newReadOneMap = Maps.newHashMap();

		for (Map.Entry<String, Object> readOneEntry : readOneMap.entrySet()) {
			if ("object_id".equals(readOneEntry.getKey())) {
				continue;
			}

			newReadOneMap.put("where_and_eq_" + readOneEntry.getKey(), Boolean.TRUE.toString());
			newReadOneMap.put("where_and_eq_" + readOneEntry.getKey() + "_value", readOneEntry.getValue());
		}

		newReadOneMap.put("object_id", readOneMap.get("object_id"));

		return this.readOne(requiredType, sqlFilePath, newReadOneMap);
	}

	protected <R> R readOne(Class<R> requiredType, String sqlFilePath, Map<String, ?> readOne) {
		List<R> readList = this.readList(requiredType, sqlFilePath, readOne);

		if (CollectionUtils.isEmpty(readList)) {
			return null;
		}

		if (readList.size() > 1) {
			log.error("单条数据查询方法，查询出" + readList.size() + "条数据:sqlFilePath=" + sqlFilePath + ", readOne=" + readOne);
		}

		return readList.get(0);
	}
}